Anomaly Detection is the task of identifying the rare items, events or observations which raise suspicions by differing significantly from the majority of the data. Typically the anomalous items will translate to some kind of problem such as bank fraud, a structural defect, medical problems or errors in a text. There are three broad categories of anomaly detection techniques exist:
Datasets have been generated by the TRAFAIR project and the data are available on the Italian open data portal
You can download the data from the original source found here and load it using pandas (Learn How) or you can use PyCaret's data respository to load the data using get_data() function (This will require internet connection).
import pycaret
import pandas as pd
dataset = pd.read_csv('4005_20200101_20200331.csv')
#check the shape of data
dataset.shape
In order to demonstrate the predict_model() function on unseen data, a sample of 5% (54 samples) are taken out from original dataset to be used for predictions at the end of experiment. This should not be confused with train/test split. This particular split is performed to simulate real life scenario. Another way to think about this is that these 54 samples are not available at the time when this experiment was performed.
data = dataset.sample(frac=0.95, random_state=786)
data_unseen = dataset.drop(data.index)
data.reset_index(drop=True, inplace=True)
data_unseen.reset_index(drop=True, inplace=True)
print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))
setup() function initializes the environment in PyCaret and creates the transformation pipeline to prepare the data for modeling and deployment. setup() must be called before executing any other function in PyCaret. It takes only one mandatory parameter: pandas dataframe. All other parameters are optional and are used to customize pre-processing pipeline (we will see them in later tutorials).
When setup() is executed, PyCaret's inference algorithm will automatically infer the data types for all features based on certain properties. Although, most of the times the data type is inferred correctly but it's not always the case. Therefore, after setup() is executed, PyCaret displays a table containing features and their inferred data types. At which stage, you can inspect and press enter to continue if all data types are correctly inferred or type quit to end the experiment. Identifying data types correctly is of fundamental importance in PyCaret as it automatically performs few pre-processing tasks which are imperative to perform any machine learning experiment. These pre-processing tasks are performed differently for each data type. As such, it is very important that data types are correctly configured.
In later tutorials we will learn how to overwrite PyCaret's inferred data types using numeric_features and categorical_features parameter in setup().
from pycaret.anomaly import *
exp_ano101 = setup(data, normalize = True,
session_id = 123)
Once the setup is succesfully executed it prints the information grid that contains few important information. Much of the information is related to pre-processing pipeline which is constructed when setup() is executed. Much of these features are out of scope for the purpose of this tutorial. However, few important things to note at this stage are:
session_id is passed, a random number is automatically generated that is distributed to all functions. In this experiment session_id is set as 123 for later reproducibility.True. Notice that Missing Values in the information grid above is True as the data contains missing values which are automatically imputed using mean for numeric features and constant for categorical features. The method of imputation can be changed using numeric_imputation and categorical_imputation parameter in setup(). MouseID using ignore_feature parameter. Notice that how few tasks such as missing value imputation and categorical encoding that are imperative to perform modeling are automatically handled. Most of the other parameters in setup() are optional and used for customizing pre-processing pipeline. These parameters are out of scope for this tutorial but as you progress to intermediate and expert level, we will cover them in much detail.
Creating an anomaly detection model in PyCaret is simple and similar to how you would have created a model in supervised modules of PyCaret. The anomaly detection model is created using create_model() function which takes one mandatory parameter i.e. name of the model as a string. This function returns a trained model object. See the example below:
models()
iforest = create_model('iforest')
print(iforest)
We have created Isolation Forest model using create_model(). Notice the contamination parameter is set 0.05 which is the default value when you do not pass fraction parameter in create_model(). fraction parameter determines the proportion of outliers in the dataset. In below example, we will create One Class Support Vector Machine model with 0.025 fraction.
svm = create_model('svm', fraction = 0.025)
print(svm)
Just by replacing iforest with svm inside create_model() we have now created OCSVM anomaly detection model. There are 12 models available ready-to-use in pycaret.anomaly module. To see the complete list, please see docstring or use models function.
knn = create_model('knn')
print(knn)
cluster = create_model('cluster')
print(cluster)
abod = create_model('abod')
print(abod)
histogram = create_model('histogram')
print(histogram)
lof = create_model('lof')
print(lof)
pca = create_model('pca')
print(pca)
mcd = create_model('mcd')
print(mcd)
Now that we have created a model, we would like to assign the anomaly labels to our dataset (1080 samples) to analyze the results. We will achieve this by using assign_model() function. See an example below:
iforest_results = assign_model(iforest)
iforest_results.head()
svm_results = assign_model(svm)
svm_results.head()
knn_results = assign_model(knn)
knn_results.head()
cluster_results = assign_model(cluster)
cluster_results.head()
abod_results = assign_model(abod)
abod_results.head()
histogram_results = assign_model(histogram)
histogram_results.head()
lof_results = assign_model(lof)
lof_results.head()
pca_results = assign_model(pca)
pca_results.head()
mcd_results = assign_model(mcd)
mcd_results.head()
Notice that two columns Label and Score are added towards the end. 0 stands for inliers and 1 for outliers/anomalies. Score is the values computed by the algorithm. Outliers are assigned with larger anomaly scores. Notice that iforest_results also includes MouseID feature that we have dropped during setup(). It wasn't used for the model and is only appended to the dataset when you use assign_model(). In the next section we will see how to analyze the results of anomaly detection using plot_model().
plot_model() function can be used to analyze the anomaly detection model over different aspects. This function takes a trained model object and returns a plot. See the examples below:
plot_model(iforest)
plot_model(svm)
plot_model(knn)
plot_model(cluster)
plot_model(abod)
plot_model(histogram)
plot_model(lof)
plot_model(pca)
plot_model(mcd)
plot_model(iforest, plot = 'umap')
plot_model(svm, plot = 'umap')
plot_model(cluster, plot = 'umap')
plot_model(knn, plot = 'umap')
plot_model(abod, plot = 'umap')
plot_model(histogram, plot = 'umap')
plot_model(lof, plot = 'umap')
plot_model(pca, plot = 'umap')
plot_model(mcd, plot = 'umap')
predict_model() function is used to assign anomaly labels on the new unseen dataset. We will now use our iforest model to predict the data stored in data_unseen. This was created in the beginning of the experiment and it contains 54 new samples that were not exposed to PyCaret before.
unseen_predictions = predict_model(iforest, data=data_unseen)
unseen_predictions.head()
Label column indicates the outlier (1 = outlier, 0 = inlier). Score is the values computed by the algorithm. Outliers are assigned with larger anomaly scores. You can also use predict_model() function to label the training data. See example below:
data_predictions = predict_model(knn, data = data)
data_predictions.head()
data_predictions = predict_model(svm, data = data)
data_predictions.head()
data_predictions = predict_model(cluster, data = data)
data_predictions.head()
data_predictions = predict_model(abod, data = data)
data_predictions.head()
data_predictions = predict_model(histogram, data = data)
data_predictions.head()
data_predictions = predict_model(lof, data = data)
data_predictions.head()
data_predictions = predict_model(pca, data = data)
data_predictions.head()
data_predictions = predict_model(mcd, data = data)
data_predictions.head()
We have now finished the experiment by using our iforest model to predict outlier labels on unseen data. This brings us to the end of our experiment but one question is still to be asked. What happens when you have more new data to predict? Do you have to go through the entire experiment again? The answer is No, you don't need to rerun the entire experiment and reconstruct the pipeline to generate predictions on new data. PyCaret's inbuilt function save_model() allows you to save the model along with entire transformation pipeline for later use.
save_model(iforest,'Anom_detection_iforest')
save_model(svm,'Anom_detection_svm')
save_model(knn,'Anom_detection_knn')
save_model(cluster,'Anom_detection_cluster')
save_model(abod,'Anom_detection_abod')
save_model(histogram,'Anom_detection_histogram')
save_model(lof,'Anom_detection_lof')
save_model(pca,'Anom_detection_pca')
save_model(mcd,'Anom_detection_mcd')
To load a saved model on a future date in the same or different environment, we would use the PyCaret's load_model() function and then easily apply the saved model on new unseen data for prediction
saved_iforest = load_model('Anom_detection_iforest')
Once the model is loaded in the environment, you can simply use it to predict on any new data using the same predict_model() function . Below we have applied the loaded model to predict the same data_unseen that we have used in section 10 above.
new_prediction = predict_model(saved_iforest, data=data_unseen)
new_prediction.head()
saved_svm = load_model('Anom_detection_svm')
new_prediction = predict_model(saved_svm, data=data_unseen)
new_prediction.head()
Notice that results of unseen_predictions and new_prediction are identical.
saved_knn = load_model('Anom_detection_knn')
new_prediction = predict_model(saved_knn, data=data_unseen)
new_prediction.head()
saved_cluster = load_model('Anom_detection_cluster')
new_prediction = predict_model(saved_cluster, data=data_unseen)
new_prediction.head()
saved_adob = load_model('Anom_detection_abod')
new_prediction = predict_model(saved_adob, data=data_unseen)
new_prediction.head()
saved_histogram = load_model('Anom_detection_histogram')
new_prediction = predict_model(saved_histogram, data=data_unseen)
new_prediction.head()
saved_lof = load_model('Anom_detection_lof')
new_prediction = predict_model(saved_lof, data=data_unseen)
new_prediction.head()
saved_pca = load_model('Anom_detection_pca')
new_prediction = predict_model(saved_pca, data=data_unseen)
new_prediction.head()
saved_mcd = load_model('Anom_detection_mcd')
new_prediction = predict_model(saved_mcd, data=data_unseen)
new_prediction.head()